package chances.epg.api.controller;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import chances.epg.api.config.EpgApiMvcConfig;
import chances.epg.api.controller.model.ResultSetResponse;
import chances.epg.api.tools.ContentTool;
import chances.epg.commons.log.EpgLogFactory;
import chances.epg.commons.utils.DateUtils;
import chances.epg.commons.utils.JSONUtils;
import chances.epg.commons.utils.PathUtils;
import chances.epg.commons.utils.RequestUtils;
import chances.epg.data.PageBean;
import chances.epg.entity.content.CategoryItem;
import chances.epg.entity.content.EpgContent;
import chances.epg.entity.content.Episode;
import chances.epg.entity.content.Series;
import chances.epg.navigator.context.AccessContext;
import chances.epg.search.searcher.SearchRequest;
import chances.epg.search.searcher.SearchResult;
import chances.epg.search.searcher.SearchService;

@RestController
public class SearchContentController extends AbstractDataController {
	private static final Logger LOGGER = EpgLogFactory.getSearchLogger();

	@Autowired
	private SearchService searchService;

	@Autowired
	private EpgApiMvcConfig epgApiMvcConfig;

	private List<String> imageAttrs = Arrays.asList("poster", "still", "opImg1", "opImg2");

	/**
	 * 关联搜索
	 * 
	 * @param model
	 * @param request
	 * @param response
	 * @return
	 * @throws IOException
	 */
	@RequestMapping(value = "/search/relation")
	public ResultSetResponse<Map<String, Object>> searchRelation(ModelMap model, HttpServletRequest request,
			HttpServletResponse response) throws IOException {
		int result = SUCCESS;
		LOGGER.debug("/api/search/relation request:" + request.getQueryString());
		SearchResult searchResult = new SearchResult();

		SearchRequest res = this.createSearchRequest(request);
		try {
			res = this.createSearchRequest(request);
			String action = res.getAction();
			if ("byPerson".equals(action)) {
				searchResult = this.searchService.getSearchHelper().searchByPersons(res);
			} else if ("byTag".equals(action)) {
				searchResult = this.searchService.getSearchHelper().searchByTags(res);
			} else {
				result = NOT_SUPPORT_SEARCH;
				LOGGER.error("Unsupport search mothed,action=" + action);
			}
		} catch (Exception ex) {
			result = SEARCH_ERROR;
			LOGGER.error("search error.", ex);
		}

		List<Map<String, Object>> contents = new ArrayList<Map<String, Object>>();
		if (result == SUCCESS) {
			for (Object obj : searchResult.getResult()) {
				Map<String, Object> c = JSONUtils.toMap(obj.toString());
				imageHandler(c);
				contents.add(c);
			}
		}

		return new ResultSetResponse<Map<String, Object>>(result, contents, new PageBean());
	}

	private void imageHandler(Map<String, Object> c) {
		imageAttrs.forEach(s -> {
			String name = (String) c.get(s);
			if (StringUtils.isNotEmpty(name)) {
				name = PathUtils.join(this.epgApiMvcConfig.getResourcePath(), name);
				c.put(s, name);
			}
		});
	}
	
	@RequestMapping(value = "/search/group")
	public ResultSetResponse<Map<String, String>> searchInitalsGroup(ModelMap model, HttpServletRequest request,
			HttpServletResponse response) throws IOException {

		String initals = RequestUtils.getParameter(request, "initals", "");
		String type = RequestUtils.getParameter(request, "type", EpgContent.SEARCH_GROUP);
		int result = SUCCESS;
		List<Map<String, String>> searchResult = null;
		try {
			searchResult = this.contentService.searchInitalsGroup(initals, type);
		} catch (DataAccessException ex) {
			result = DB_ERROR;
			LOGGER.error(ex.getMessage(), ex);
		} catch (Throwable ex) {
			result = ERROR;
			LOGGER.error(ex.getMessage(), ex);
		}
		return new ResultSetResponse<>(result, searchResult, null);
	}

	@RequestMapping(value = "/search/search")
	public ResultSetResponse<EpgContent> searchByName(ModelMap model, HttpServletRequest request,
			HttpServletResponse response) throws IOException {
		
		LOGGER.debug("search/search request:" + request.getQueryString());
		String initals = RequestUtils.getParameter(request, "initals", "");
		String baseTypeCode = RequestUtils.getParameter(request, "type", "");
		String tagString = RequestUtils.getParameter(request, "tagString", "");
		int size = RequestUtils.getParameter(request, "size", DEFAULT_SIZE);
		int pageIndex = RequestUtils.getParameter(request, "pageindex", 1);

		int result = SUCCESS;
		PageBean pageBean = this.createPageBean(size, pageIndex);
		List<EpgContent> contentList = null;

		try {
			contentList = this.contentService.searchContentByInitals(initals, baseTypeCode, tagString, pageBean);
			for (EpgContent content : contentList) {
				
				//设置类型
				if(StringUtils.isNotBlank(content.getContentBaseTags())){
					String baseTags = ContentTool.getInstance().baseTagNames(content.getContentBaseTags());
					content.setOpImg2(baseTags);
				}
				
				if (content.getType().equals(CategoryItem.ITEMTYPE_SERIES)
						|| content.getType().equals(CategoryItem.ITEMTYPE_SERIES2)) {
					List<Episode> episodes = this.contentService.getEpisodes(content.getContentCode(),content.getType());
					content.setEpisodes(episodes);
				}
			}
		} catch (DataAccessException ex) {
			result = DB_ERROR;
			LOGGER.error(ex.getMessage(), ex);
		} catch (Throwable ex) {
			result = ERROR;
			LOGGER.error(ex.getMessage(), ex);
		}

		return new ResultSetResponse<EpgContent>(result, contentList, pageBean);

	}

	@RequestMapping(value = "/search/filter")
	public ResultSetResponse<Map<String, Object>> searchByCondition(ModelMap model, HttpServletRequest request,
			HttpServletResponse response) throws IOException {
		LOGGER.debug("/search/filter request:" + request.getQueryString());
		int result = SUCCESS;
		String type = RequestUtils.getParameter(request, "type", "");
		String category = RequestUtils.getParameter(request, "category", "");
		String region = RequestUtils.getParameter(request, "region", "");
		String year = RequestUtils.getParameter(request, "year", "");
		boolean early = RequestUtils.getParameter(request, "early", false);
		int orderBy = RequestUtils.getParameter(request, "orderby", 1);
		int size = RequestUtils.getParameter(request, "size", 10);
		int pageIndex = RequestUtils.getParameter(request, "p_idx", 1);
		String siteCode = RequestUtils.getParameter(request, "site", "hdvod");
		int randomSize = RequestUtils.getParameter(request, "rSize", 100);
		boolean isRandom = RequestUtils.getParameter(request, "isRandom", false);
		SearchResult searchResult = new SearchResult();
		try {
			searchResult = this.searchService.getSearchHelper().filter(type, category, region, year, early, orderBy, pageIndex,
					size, isRandom, randomSize);
		} catch (Exception ex) {
			result = SEARCH_ERROR;
			LOGGER.error("search error.", ex);
		}
		AccessContext context = this.createAccessContext(request);
		context.setSiteCode(siteCode);
		List<Map<String, Object>> contents = new ArrayList<Map<String, Object>>();
		if (result == SUCCESS) {
			for (Object obj : searchResult.getResult()) {
				Map<String, Object> c = JSONUtils.toMap(obj.toString());
				if (CategoryItem.ITEMTYPE_SERIES.equals(c.get("type"))
						|| CategoryItem.ITEMTYPE_SERIES2.equals(c.get("type"))) {
					Series series = this.contentService.getSeriesByCode(c.get("contentCode") + "");
					List<Episode> episodes = this.contentService.getEpisodes(c.get("contentCode") + "", series.getSeriesType());
					c.put("childrenTitle", "");
					c.put("isFinished", false);
					c.put("updateNum", 0);
					if (episodes.size() > 0) {
						if(series.getSeriesType().equals(CategoryItem.ITEMTYPE_SERIES)){
							c.put("isFinished", (series.getEpisodeNumber() == episodes.get(episodes.size()-1).getEpisodeIndex()));
							c.put("updateNum", episodes.get(episodes.size()-1).getEpisodeIndex());
						}else if(series.getSeriesType().equals(CategoryItem.ITEMTYPE_SERIES2)){
							c.put("childrenTitle", episodes.get(0).getContentTitle());
							//系列剧使用MM-dd作为更新期数
							if(null!=episodes.get(0).getIssueDate()){
								c.put("updateNum", DateUtils.formatDateMMdd(episodes.get(0).getIssueDate()));
							}
							//系列剧使用横图
							c.put("still", series.getStill());
						}
					}
				}
				c.put("url", this.getResultItemUrl(context, c));
				imageHandler(c);
				contents.add(c);
			}
		}
		PageBean pageBean = new PageBean(size);
		pageBean.setCurrentPage(pageIndex);
		pageBean.setRecordCount(searchResult.getTotalCount());
		return new ResultSetResponse<Map<String, Object>>(result, contents, pageBean);
	}

	private SearchRequest createSearchRequest(HttpServletRequest request) {
		SearchRequest res = new SearchRequest();
		String action = request.getParameter("action");
		res.setAction(action);

		String condition = request.getParameter("condition");
		if (StringUtils.isNotBlank(condition)) {
			try {
				res.setCondition(URLDecoder.decode(condition, "utf-8"));
			} catch (UnsupportedEncodingException e) {
				LOGGER.error(e.getMessage(), e);
			}
		}

		String curPage = request.getParameter("pageindex");
		if (StringUtils.isNotEmpty(curPage) && StringUtils.isNumeric(curPage)) {
			res.setCurPage(Integer.parseInt(curPage));
		}

		String pageSize = request.getParameter("size");
		if (StringUtils.isNotEmpty(pageSize) && StringUtils.isNumeric(pageSize)) {
			res.setPagesize(Integer.parseInt(pageSize));
		}

		String type = request.getParameter("type");
		if (StringUtils.isNotEmpty(type)) {
			res.setType(type);
		}

		String contentCode = request.getParameter("code");
		if (StringUtils.isNotEmpty(contentCode)) {
			res.setContentCode(contentCode);
		}
		
		String hdType = request.getParameter("hdtype");
		if (StringUtils.isNotEmpty(hdType)) {
			res.setHdType(hdType);
		}
		
		return res;
	}
}
